/*
 * Copyright (c) 2009 Frederic Daoud
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.stripesbook.rayures.service.impl;

import static org.stripesbook.rayures.util.Constants.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.config.ConfigurableComponent;
import net.sourceforge.stripes.config.Configuration;
import net.sourceforge.stripes.util.Log;
import org.stripesbook.rayures.action.RayuresActionBean;
import org.stripesbook.rayures.service.LookupStrategy;
import org.stripesbook.rayures.service.ResourceBundleResolver;
import org.stripesbook.rayures.service.TemplateEngine;
import org.stripesbook.rayures.service.ViewPreparer;
import org.stripesbook.rayures.util.Location;
import org.stripesbook.rayures.util.MapBundle;
import org.stripesbook.rayures.util.Resolver;
import org.stripesbook.rayures.view.ViewContext;
import org.stripesbook.rayures.view.ViewObject;
import org.stripesbook.rayures.view.stripes.SMessages;
import org.stripesbook.rayures.view.util.Formatter;

public class ViewPreparerImpl implements ViewPreparer, ConfigurableComponent {
  private static final Log log = Log.getInstance(ViewPreparerImpl.class);

  private TemplateEngine templateEngine;
  private ResourceBundleResolver resourceBundleResolver;
  private LookupStrategy lookupStrategy;
  private String layoutFile;
 
  public void init(Configuration config) throws Exception {
    templateEngine = Resolver.resolve(config, TemplateEngine.class);
    resourceBundleResolver = Resolver.resolve(config, ResourceBundleResolver.class);
    lookupStrategy = Resolver.resolve(config, LookupStrategy.class);

    layoutFile = config.getBootstrapPropertyResolver().getFilterConfig()
      .getInitParameter(CONFIG_LAYOUT_FILE); 

    if (layoutFile == null) {
      layoutFile = DEFAULT_LAYOUT_FILE;
    }
  }

  public void prepareView(ActionBean actionBean, String eventName) {
    ViewContext viewContext = prepareViewContext(actionBean, eventName);
    setConvenienceAttributes(actionBean.getContext().getRequest(), viewContext);
    injectViewContextIntoActionBean(actionBean, viewContext);
    resolveLayout(actionBean, eventName);
    addViewObjectToRequest(actionBean);
  }

  protected ViewContext prepareViewContext(ActionBean actionBean, String eventName) {
    HttpServletRequest request = actionBean.getContext().getRequest();
    Locale locale = request.getLocale();

    MapBundle bundle = resourceBundleResolver.resolveResourceBundles(
      locale, actionBean, eventName);

    return new ViewContext(actionBean, templateEngine, resourceBundleResolver, locale, bundle);
  }

  protected void setConvenienceAttributes(HttpServletRequest request, ViewContext viewContext) {
    MapBundle bundle = viewContext.getBundle();
    Locale locale = request.getLocale();

    request.setAttribute(ATTR_BUNDLE, bundle);
    request.setAttribute(ATTR_CONTEXT_PATH, request.getContextPath());
    request.setAttribute(ATTR_FORMATTER, new Formatter(locale));
    request.setAttribute(ATTR_LOCALE, locale);
    request.setAttribute(ATTR_MESSAGES, ViewObject.tag(SMessages.class, viewContext));
  }

  protected void injectViewContextIntoActionBean(ActionBean actionBean, ViewContext viewContext) {
    if (actionBean instanceof RayuresActionBean) {
      ((RayuresActionBean) actionBean).setViewContext(viewContext);
    }
  }

  protected void resolveLayout(ActionBean actionBean, String eventName) {
    for (String layout : getLayoutSearchLocations(actionBean, eventName)) {
      if (templateEngine.isTemplateFileNameValid(layout)) {
        log.debug("Using layout: ", layout);
        actionBean.getContext().getRequest().setAttribute(ATTR_LAYOUT, layout);
        break;
      }
    }
  }

  protected List<String> getLayoutSearchLocations(ActionBean actionBean, String eventName) {
    List<String> list = new ArrayList<String>();
    
    for (Location location : lookupStrategy.getSearchLocations(actionBean, eventName)) {
      String layout = location.getFilePath(layoutFile, "_" + layoutFile);
      list.add(layout);
    }
    return list;
  }

  protected void addViewObjectToRequest(ActionBean actionBean) {
    if (actionBean instanceof RayuresActionBean) {
      Object viewObject = ((RayuresActionBean) actionBean).getView();
      actionBean.getContext().getRequest().setAttribute(ATTR_VIEW, viewObject);
    }
  }
}
